class AutoDict(dict):
    """
    A dictionary which sets all items to a default thing on lookup if it's
    missing.
    """
    def __init__(self, default, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.__default = default
        
    def __getitem__(self, item):
        if not dict.__contains__(self, item):
            default = self.__default
            if callable(default):
                default = default()
            dict.__setitem__(self, item, default)
        return dict.__getitem__(self, item)
    
    
class FixedTypeKeyDictionary(dict):
    """
    A dictionary which forces a certain type on all it's keys.
    """
    def __init__(self, fixed_type=str, *args, **kwargs):
        self._fixed_type = fixed_type
        dict.__init__(self, *args, **kwargs)
        
    def __setitem__(self, key, value):
        dict.__setitem__(self, self._fixed_type(key), value)
        
    def __getitem__(self, key):
        return dict.__getitem__(self, self._fixed_type(key))
        
    def __contains__(self, key):
        return dict.__contains__(self, self._fixed_type(key))
        
    def __delitem__(self, key):
        dict.__delitem__(self, self._fixed_type(key))
        
        
class CachedInstancesObject(object):
    _cache = {}
    _positional = 0
    _named      = ''
    def __new__(cls, *args, **kwargs):
        if len(args) <= cls._positional:
            raise ValueError("Argument <steamid> is required. \n \
            Syntaxes: \n \
            ========= \n \
            steamlib.Player(\"steamid\") \n \
            steamlib.Stats(\"steamid\")")
        elif len(args) >= cls._positional:
            key = args[cls._positional]
        else:
            key = kwargs[cls._named]
        if key in cls._cache:
            return cls._cache[key]
        new = object.__new__(cls)
        new.init(*args, **kwargs)
        cls._cache[key] = new
        return new
    
    def init(self, *args, **kwargs):
        pass
